﻿''' <summary>
''' Represents a console command and parameters parsed from a string of command line text.
''' </summary>
Public Class CommandLine
    Private argString As String
    Private rawString As String
    Private commandWord As String
    Private parameters As New Dictionary(Of String, String)

    ''' <summary>
    ''' Gets the command keyword.
    ''' </summary>
    ''' <returns></returns>
    Public ReadOnly Property Command As String
        Get
            Return commandWord
        End Get
    End Property

    ''' <summary>
    ''' Gets or sets the custom status result for this command.  Default is Nothing (Null).
    ''' </summary>
    ''' <returns></returns>
    Public Property CustomStatus As String

    ''' <summary>
    ''' Gets the number of parameters parsed from this command line.
    ''' </summary>
    ''' <returns></returns>
    Public ReadOnly Property ParameterCount As Integer
        Get
            Return parameters.Count
        End Get
    End Property

    ''' <summary>
    ''' Gets the name of the parameter at the specified index.  If the parameter was a key-value pair, this property
    ''' will be the key.  If the parameter was not a key-value pair then this value will be "%n" where "n" is the parameter's
    ''' index.
    ''' </summary>
    ''' <param name="index">The zero-based index of the parameter.</param>
    ''' <returns></returns>
    Public ReadOnly Property ParameterName(index As Integer) As String
        Get
            If index > -1 AndAlso index < parameters.Count Then
                Return parameters.Keys.ElementAt(index)
            End If
            Return String.Empty
        End Get
    End Property

    ''' <summary>
    ''' Gets the value for the parameter with the specified name.  If the parameter was a key-value pair, this property
    ''' will be the value.  If the parameter was not a key-value pair then this value will be the text supplied.
    ''' </summary>
    ''' <param name="parameterName">The name of the parameter.</param>
    ''' <returns></returns>
    Public ReadOnly Property ParameterValue(parameterName As String) As String
        Get
            If parameters.ContainsKey(parameterName) Then Return parameters(parameterName)
            Return String.Empty
        End Get
    End Property

    ''' <summary>
    ''' Gets the value for the parameter at the specified index.  If the parameter was a key-value pair, this property
    ''' will be the value.  If the parameter was not a key-value pair then this value will be the text supplied.
    ''' </summary>
    ''' <param name="index"></param>
    ''' <returns></returns>
    Public ReadOnly Property ParameterValue(index As Integer) As String
        Get
            If index > -1 AndAlso index < parameters.Count Then
                Return parameters.Values.ElementAt(index)
            End If
            Return String.Empty
        End Get
    End Property

    Public Sub New(line As String)
        rawString = line
        Dim firstSpaceIndex As Integer = line.IndexOf(" "c)
        If firstSpaceIndex > -1 Then
            commandWord = line.Substring(0, firstSpaceIndex).ToLower
            argString = line.Substring(firstSpaceIndex + 1)
            If argString.Length > 0 Then
                Dim params() As String
                Using ms As New IO.MemoryStream(Text.Encoding.Default.GetBytes(argString))
                    Using tfp As New FileIO.TextFieldParser(ms)
                        tfp.HasFieldsEnclosedInQuotes = True
                        tfp.SetDelimiters(" "c)
                        params = tfp.ReadFields
                    End Using
                End Using
                For Each param In params
                    If param.Count(Function(c) c = "="c) = 1 Then
                        Dim parts() As String = param.Split("="c)
                        parameters(parts(0)) = parts(1)
                    Else
                        parameters($"%{parameters.Count}") = param
                    End If
                Next
            End If
        Else
            commandWord = line
        End If
    End Sub

    ''' <summary>
    ''' Gets the original command line string from which this instance was parsed.
    ''' </summary>
    ''' <returns></returns>
    Public Function GetOriginalCommandLine() As String
        Return rawString
    End Function

    ''' <summary>
    ''' Gets the parameters portion of the raw string provided.
    ''' </summary>
    ''' <returns></returns>
    Public Function GetParameterString() As String
        Return argString
    End Function
End Class
